﻿using System;
using System.Collections.Generic;
using System.Linq;
using EzDesk.EzAppApi.Utility;
using EzDesk.Utility.Json;
using EzDesk.Apps.Model.Message;
using EzDesk.Apps.Model;
using EzDesk.Apps.Interface.Message;
using EzDesk.Core.Model;
using EzDesk.Utility.Generic;
using EzDesk.Utility.ServiceStatusInfo;
using EzDesk.Utility.Web.Extensions;
using Microsoft.Practices.Unity;
using EzDesk.Utility.Log;

namespace EzDesk.Apps.ServiceImpl.Message
{
    public class TopicService : ContainerAccessorBase, ITopicService
    {
        private const string FeedTemplateStr_message_receiveMsgUpdate = "message_receiveMsgUpdate";
        private const string FeedTemplateStr_message_receiveMsgConfirm = "message_receiveMsgConfirm";

        private IEzApiClient EzApiClient
        {
            get { return EzAppApi.Utility.EzApiClient.Instance; }
        }

        #region [ 构造器 ]
        private EzDeskMessageDataContext _db;

        public TopicService()
        {
            this._db = Container.Resolve<EzDeskMessageDataContext>();

            LogEx.TRACE("TopicService", "初始化TopicService");
        }

        public TopicService(IEzApiClient apiClient, EzDeskMessageDataContext db)
        {
            this._db = db;
            LogEx.TRACE("TopicService", "初始化TopicService");
        }
        #endregion

        #region [private methods]
        /// <summary>
        /// 发出新消息时的各种feed发送
        /// </summary>
        /// <param name="messageText"></param>
        /// <param name="topicId"></param>
        /// <param name="senderId"></param>
        /// <param name="messageTitle"></param>
        /// <param name="isNeedConfirm"></param>
        /// <param name="memberString"></param>
        private void sendCreateTopicFeeds(string messageText, Guid topicId, Guid senderId, string messageTitle, bool isNeedConfirm, string memberString)
        {
            string updateFeedMemberString = EzDeskAppApiHelper.MemberStringHelper.JoinUserId(memberString, senderId);

            if (!isNeedConfirm)
            {
                // 发送 不需要确认的消息 的 Update 通知
                var feedData = new Dictionary<string, string>()
                                   {
                                       {"senderId", senderId.ToString()},
                                       {
                                           "senderName",
                                           EzApiClient.GetSimpleUserById(senderId).Name
                                           },
                                       {"messageId", topicId.ToString()},
                                       {"messageTitle", messageTitle},
                                       {"messageText", messageText.SummrizeText(50)},
                                       {"replyCount", "0"},
                                       {"latestReply", ""},
                                   };

                var feedId = EzApiClient.SendFeed(
                    FeedTemplateStr_message_receiveMsgUpdate,
                    JsonHelper.ConvertToJson(feedData),
                    updateFeedMemberString,
                    senderId
                    );

                // 修改FeedData 单独更新自己的FeedData
                feedData.Clear();
                feedData["senderName"] = "我";

                EzApiClient.UpdatePersonalFeedData(
                    feedId,
                    senderId.ToString(),
                    JsonHelper.ConvertToJson(feedData)
                    );

                EzApiClient.SetFeedRecord(
                    topicId,
                    FeedTemplateStr_message_receiveMsgUpdate,
                    updateFeedMemberString,
                    feedId, null
                    );
            }
            else
            {
                // 发送 需要确认的消息 的 Update 通知
                var feedData = new Dictionary<string, string>()
                                   {
                                       {
                                           "senderName",
                                           EzApiClient.GetSimpleUserById(senderId).Name
                                           },
                                       {"messageId", topicId.ToString()},
                                       {"messageTitle", messageTitle},
                                       {"messageText", messageText.SummrizeText(50)},
                                       {"replyCount", "0"},
                                       {"confirmCount", "0"},
                                       {"confirmStatus", "还没有人确认过。"},
                                       {"confirmLink", "确认收到"},
                                       {"latestReply", ""},
                                   };
                var feedId = EzApiClient.SendFeed(
                    FeedTemplateStr_message_receiveMsgConfirm,
                    JsonHelper.ConvertToJson(feedData),
                    updateFeedMemberString,
                    senderId
                    );

                // 修改FeedData 单独更新自己的FeedData
                feedData.Clear();
                feedData["senderName"] = "我";
                feedData["confirmLink"] = "";

                EzApiClient.UpdatePersonalFeedData(
                    feedId,
                    senderId.ToString(),
                    JsonHelper.ConvertToJson(feedData)
                    );
                // 将自己收到的feed先变成update
                EzApiClient.UpdatePersonalFeedType(feedId, senderId.ToString(), "update");

                EzApiClient.SetFeedRecord(
                    topicId,
                    FeedTemplateStr_message_receiveMsgConfirm,
                    updateFeedMemberString,
                    feedId, null
                    );
            }
        }
        #endregion


        /// <summary>
        /// 创建新的消息
        /// </summary>
        /// <returns>新消息的ID</returns>
        public StatusInfo<Guid> CreateNewTopic(
            Guid senderId, 
            string messageTitle, 
            string messageText, 
            bool isNeedConfirm, 
            string memberString
            )
        {
            return StatusInfo.Wrap(
                () =>
                    {
                        Guid topicId = Guid.NewGuid();

                        // 保存新的消息
                        using (var db = new EzDeskMessageDataContext())
                        {
                            var newMsg = new ez_Message()
                                             {
                                                 MessageId = topicId,
                                                 ParentId = topicId,
                                                 CreateOn = DateTime.Now,
                                                 SenderId = senderId,
                                                 Title = messageTitle,
                                                 Text = messageText,
                                                 NeedConfirm = isNeedConfirm,
                                                 MemberString = memberString,
                                             };
                            db.ez_Messages.InsertOnSubmit(newMsg);
                            db.SubmitChanges();
                        }

                        // 发送各种通知
                        sendCreateTopicFeeds(messageText, topicId, senderId, messageTitle,
                                             isNeedConfirm, memberString);

                        //写入收件箱
                        createMessageInbox(topicId, memberString, senderId);

                        return topicId;
                    });
        }

        /// <summary>
        /// 回复一条消息
        /// </summary>
        /// <param name="senderId"></param>
        /// <param name="messageText"></param>
        /// <param name="memberString"></param>
        /// <param name="needConfirm"></param>
        public StatusInfo ReplyToMessage(Guid senderId, Guid replyToMessageId, Guid topicId, string replyText, bool isReplyToAll)
        {
            return StatusInfo.Wrap(
                () =>
                    {
                        var actor = EzApiClient.GetSimpleUserById(senderId);

                        //去掉回复内容的html
                        string replyTextContent = replyText.RemoveHtml();

                        // 找被回复的消息
                        var replyToMessage = _db.ez_Messages.Where(p => p.MessageId == replyToMessageId)
                            .SingleOrDefault();
                        if (replyToMessage == null)
                        {
                            //todo: 没找到要回复的消息
                            throw new Exception("Message Not Found!");
                        }

                        // 找被回复的消息的主题
                        ez_Message topicMessage = null;
                        if (topicId != replyToMessageId)
                        {
                            topicMessage =
                                _db.ez_Messages.Where(p => p.MessageId == topicId && p.MessageId == p.ParentId)
                                    .SingleOrDefault();
                            if (topicMessage == null)
                            {
                                //todo: 没找到要回复的主题
                                throw new Exception("Topic Not Found!");
                            }
                        }
                        else
                        {
                            topicMessage = replyToMessage;
                        }


                        using (var db = new EzDeskMessageDataContext())
                        {
                            // 验证memberstring
                            Guid newMessageId = Guid.NewGuid();
                            db.ez_Messages.InsertOnSubmit(
                                new ez_Message()
                                    {
                                        MessageId = newMessageId,
                                        SenderId = senderId,
                                        MemberString = topicMessage.MemberString,
                                        ParentId = topicId,
                                        CreateOn = DateTime.Now,
                                        Title = "",
                                        Text = replyTextContent,
                                        NeedConfirm = false,
                                    }
                                );
                            db.SubmitChanges();
                        }

                        // 更新 回复数目 和 最新回复
                        topicMessage.ReplyCount++;
                        _db.SubmitChanges();

                        // 更新消息Feed 的回复数目
                        var sentFeedIds =
                            EzApiClient.GetFeedRecord(topicId, FeedTemplateStr_message_receiveMsgUpdate, null).Split(',')
                                .Union(
                                    EzApiClient.GetFeedRecord(topicId, FeedTemplateStr_message_receiveMsgConfirm, null).
                                        Split(',')
                                ).Distinct();
                        foreach (var sentFeedIdStr in sentFeedIds)
                        {
                            Guid oriFeedId;
                            if (sentFeedIdStr != null && Guid.TryParse(sentFeedIdStr, out oriFeedId))
                            {
                                var updateData = new Dictionary<string, string>()
                                                     {
                                                         {"replyCount", topicMessage.ReplyCount.ToString()},
                                                         //更新的消息回复数目
                                                         {
                                                             "latestReply",
                                                             string.Format(
                                                                 "<ez:br />最后回复 <ez:text style=\"color:#000000; font-weight: bold;\">{0}</ez:text>: <ez:text style=\"color:#666666;\">\"{1}\"</ez:text>",
                                                                 actor.Name, replyTextContent.CutString(50))
                                                             },
                                                     };
                                EzApiClient.UpdateFeedData(oriFeedId, JsonHelper.ConvertToJson(updateData));
                            }
                        }
                    });
        }

        /// <summary>
        /// 获得一个完整的主题
        /// </summary>
        /// <param name="topicId"></param>
        /// <returns></returns>
        public StatusInfo<Topic> GetFullTopic(Guid topicId, Guid actorUserId)
        {
            return StatusInfo.Wrap(
                () =>
                    {

                        Topic topic = null;
                        using (var db = new EzDeskMessageDataContext())
                        {
                            var innerTopic = db.ez_Messages.Where(p => p.MessageId == topicId).SingleOrDefault();

                            if ((innerTopic == null) || (innerTopic.ParentId != innerTopic.MessageId))
                            {
                                // todo: 没有找到合适的主题
                                throw new Exception("Topic Not Found!");
                            }

                            topic = new Topic()
                                        {
                                            MessageId = innerTopic.MessageId,
                                            CreateOn = innerTopic.CreateOn,
                                            MessageTitle = innerTopic.Title,
                                            MessageText = innerTopic.Text,
                                            Sender = EzApiClient.GetSimpleUserById(innerTopic.SenderId),
                                            Recipient = EzApiClient.GetSimpleUserById(actorUserId),
                                            NeedConfirm = innerTopic.NeedConfirm,
                                            ConfirmedInfo = getConfirmdInfo(innerTopic),
                                            ReplyList = getReplys(innerTopic),
                                            Participator = getParticipatorInfo(innerTopic.MemberString),
                                        };
                        }
                        return topic;
                    });
        }

        /// <summary>
        /// 获取发件箱
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public StatusInfo<List<Topic>> GetMessagesOutbox(Guid userId)
        {
            return StatusInfo.Wrap(
                () =>
                    {
                        using (var db = new EzDeskMessageDataContext())
                        {
                            var messages = db.ez_Messages
                                .Where(p => p.SenderId == userId && p.ParentId == p.MessageId)
                                .OrderByDescending(p => p.CreateOn);
                            return messages
                                .Select(ezMessage => new Topic()
                                                         {
                                                             MessageId = ezMessage.MessageId,
                                                             CreateOn = ezMessage.CreateOn,
                                                             MessageTitle = ezMessage.Title,
                                                             MessageText = ezMessage.Text,
                                                             Sender =
                                                                 EzApiClient.GetSimpleUserById(
                                                                     ezMessage.SenderId),
                                                             NeedConfirm = ezMessage.NeedConfirm,
                                                             ConfirmedInfo =
                                                                 getConfirmdInfo(ezMessage),
                                                             ReplyList = getReplys(ezMessage),
                                                             Participator =
                                                                 getParticipatorInfo(
                                                                     ezMessage.MemberString),
                                                         })
                                .ToList();
                        }
                    });
        }

        /// <summary>
        /// 获取收件箱
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public StatusInfo<List<Topic>> GetMessagesInbox(Guid userId)
        {
            return StatusInfo.Wrap(
                () =>
                    {
                        var messageInbox = new List<Topic>();

                        using (var db = new EzDeskMessageDataContext())
                        {
                            var messageInboxList =
                                from r in db.ez_MessageInboxes
                                from m in db.ez_Messages
                                where r.UserId == userId && r.TopicId == m.MessageId
                                orderby m.CreateOn descending
                                select m;

                            messageInbox.AddRange(messageInboxList.Select(
                                message => new Topic()
                                               {
                                                   MessageId = message.MessageId,
                                                   CreateOn = message.CreateOn,
                                                   MessageTitle = message.Title,
                                                   MessageText = message.Text,
                                                   Sender = EzApiClient.GetSimpleUserById(message.SenderId),
                                                   NeedConfirm = message.NeedConfirm,
                                                   ConfirmedInfo = getConfirmdInfo(message),
                                                   ReplyList = getReplys(message),
                                                   Participator = getParticipatorInfo(message.MemberString),
                                               }));
                        }
                        return messageInbox;
                    });
        }

        public StatusInfo<SingleMessage> GetSingleMessage(Guid messageId)
        {
            return StatusInfo.Wrap(
                () =>
                    {
                        SingleMessage singleMessage = _db.ez_Messages.Where(p => p.MessageId == messageId)
                            .Select(
                                p => new SingleMessage()
                                         {
                                             MessageId = p.MessageId,
                                             MessageTitle = p.Title,
                                             MessageText = p.Text,
                                             ParentMessageId = p.ParentId,
                                             SenderId = p.SenderId,
                                             CreateOn = p.CreateOn,
                                         }
                            )
                            .SingleOrDefault();

                        if (singleMessage == null)
                        {
                            throw new Exception("Message Not Found!");
                        }

                        return singleMessage;
                    });
        }


        /// <summary>
        /// 确认一条消息
        /// </summary>
        /// <param name="messageId"></param>
        /// <param name="actorUser"></param>
        public StatusInfo ConfirmMessage(Guid messageId, Guid actorUserId)
        {
            return StatusInfo.Wrap(
                () =>
                    {
                        var message = _db.ez_Messages
                            .Where(p => p.MessageId == messageId)
                            .SingleOrDefault();

                        if (message == null || !message.NeedConfirm)
                        {
                            // todo: error
                            throw new Exception("没有找到需要确认的消息: " + messageId.ToString());
                        }

                        if (message.SenderId == actorUserId)
                        {
                            throw new Exception("您不需要确认自己的消息");
                        }

                        var members = EzApiClient.GetAllUsersByMemberString(message.MemberString);
                        if (!members.ContainUser(actorUserId))
                        {
                            //todo: error
                            throw new Exception("您没资格确认这个消息");
                        }

                        var messageConfirm = _db.ez_MessageConfirms
                            .Where(p => p.MessageId == messageId && p.UserId == actorUserId)
                            .SingleOrDefault();
                        if (messageConfirm != null)
                        {
                            //todo: error
                            throw new Exception("已经确认过了...");
                        }


                        // 添加确认实体
                        var actor = EzApiClient.GetSimpleUserInfos(actorUserId.ToString())[0];
                        var msgConfirm = new ez_MessageConfirm()
                                             {
                                                 MessageId = messageId,
                                                 UserId = actorUserId,
                                                 UserName = actor.UserName,
                                                 ConfirmOn = DateTime.Now,
                                             };
                        using (var db = new EzDeskMessageDataContext())
                        {
                            db.ez_MessageConfirms.InsertOnSubmit(
                                msgConfirm
                                );
                            db.SubmitChanges();
                        }

                        // 更新 已确认 数目
                        message.ConfirmCount++;
                        _db.SubmitChanges();


                        // 更新消息Feed的 “已确认” 数据 和 确认状态
                        var feedIdStr = EzApiClient.GetFeedRecord(messageId, FeedTemplateStr_message_receiveMsgConfirm,
                                                                  null);

                        string confirmStatusInfo = "";
                        if (message.ConfirmCount == 1)
                        {
                            confirmStatusInfo = string.Format(
                                "<ez:text style=\"color:#000000; font-weight: bold;\">{0}</ez:text> 已经确认了这条消息。",
                                actor.Name);
                        }
                        else
                        {
                            confirmStatusInfo = string.Format(
                                "<ez:text style=\"color:#000000; font-weight: bold;\">{0}</ez:text> 等{1}人已经确认了这条消息。",
                                actor.Name, message.ConfirmCount);
                        }
                        var newFeedData = new Dictionary<string, string>()
                                              {
                                                  {"confirmCount", message.ConfirmCount.ToString()},
                                                  {"confirmStatus", confirmStatusInfo}
                                              };

                        EzApiClient.UpdateFeedsData(feedIdStr, JsonHelper.ConvertToJson(newFeedData));

                        var feedDataEx = new Dictionary<string, string>()
                                             {
                                                 {"confirmLink", ""} // 去掉本人的confirm链接
                                             };
                        EzApiClient.UpdatePersonalFeedData(Guid.Parse(feedIdStr), actorUserId.ToString(),
                                                           JsonHelper.ConvertToJson(feedDataEx));

                        // 把确认者的Notification改成Update
                        EzApiClient.UpdatePersonalFeedType(Guid.Parse(feedIdStr), actorUserId.ToString(), "update");
                    });
        }


        public StatusInfo<IList<SimpleUser>> GetPersonsInDept(Guid? deptId)
        {
            return StatusInfo.Wrap(
                () =>
                    {
                        if (deptId.HasValue && deptId.GetValueOrDefault() != Guid.Empty)
                        {
                            return EzApiClient.GetAllUsersByMemberString(
                                EzDeskAppApiHelper.MemberStringHelper.JoinGroupId(
                                    "",
                                    EzApiClient.GetDeptById(deptId.GetValueOrDefault())
                                        .GroupId.GetValueOrDefault()
                                    )
                                );
                        }

                        return EzApiClient.GetAllUsersByMemberString("everyone");
                    });
        }

        #region [ private methods ]
        /// <summary>
        /// 找出一个主题下面所有的回复
        /// </summary>
        /// <param name="innerTopic"></param>
        /// <returns></returns>
        private List<SingleMessage> getReplys(ez_Message innerTopic)
        {
           
            var replys = _db.ez_Messages.Where(p => p.ParentId == innerTopic.ParentId && p.MessageId != p.ParentId)
                .OrderBy(p => p.CreateOn)
                .Select(
                p => new SingleMessage()
                {
                    MessageId = p.MessageId,
                    MessageTitle = p.Title,
                    MessageText = p.Text,
                    ParentMessageId = p.ParentId,
                    SenderId = p.SenderId,
                    CreateOn = p.CreateOn,
                }
                ).ToList();

            return replys;
        }

        /// <summary>
        /// 找出一个主题下面的所有确认信息
        /// </summary>
        /// <param name="innerTopic"></param>
        /// <returns></returns>
        private List<MessageConfirm> getConfirmdInfo(ez_Message innerTopic)
        {
            if (!innerTopic.NeedConfirm)
            {
                return null;
            }

            var confirmedList = _db.ez_MessageConfirms.Where(p => p.MessageId == innerTopic.MessageId)
                .Select(p => new MessageConfirm()
                {
                    UserId = p.UserId,
                    ConfirmOn = p.ConfirmOn,
                }
                );

            return new List<MessageConfirm>(confirmedList);
        }


        private ParticipatorsInfo getParticipatorInfo(string memberstring)
        {
            var children = EzApiClient.GetChildrenByMemberString(memberstring);
            var groupParticipators = new List<Group>();
            var userParticipators = new List<SimpleUser>();
            foreach (var child in children)
            {
                if (child.Value == "user")
                {
                    userParticipators.Add(
                        EzApiClient.GetSimpleUserById(child.Key)
                        );

                }
                else if (child.Value == "group")
                {
                    groupParticipators.Add(
                        EzApiClient.GetGroupById(child.Key)
                        );
                }
            }

            var participator = new ParticipatorsInfo()
            {
                Memberstring = memberstring,
                AllUserMemebers = EzApiClient.GetAllUsersByMemberString(memberstring),
                GroupParticipators = groupParticipators,
                UserParticipators = userParticipators,
            };
            return participator;
        }


        /// <summary>
        /// 增添收件箱消息
        /// </summary>
        /// <param name="topicId"></param>
        /// <param name="memberString"></param>
        /// /// <param name="senderId"></param>
        private void createMessageInbox(Guid topicId, String memberString, Guid senderId)
        {
            var memberList = EzApiClient.GetAllUsersByMemberString(memberString);
            using (var db = new EzDeskMessageDataContext())
            {
                foreach (var simpleUser in memberList)
                {
                    if (senderId == simpleUser.Id) continue;
                    db.ez_MessageInboxes.InsertOnSubmit(
                        new ez_MessageInbox()
                        {
                            UserId = simpleUser.Id,
                            TopicId = topicId
                        });
                }
                db.SubmitChanges();
            }
        }
        #endregion



        protected override IUnityContainer buildContainer()
        {
            return new UnityContainer()
                .RegisterInstance(new EzDeskMessageDataContext());
        }



    }
}


